#pragma once

#include <iostream>
#include <sys/poll.h>
#include "Log.hpp"
#include "Error.hpp"
#include "sock_tcp.hpp"
#include "sock_tcp.hpp"

class PollServer
{
private:
    // typedef
    typedef struct pollfd FDEvent_t;
    // const
    static const int N = 4080;
    static const int defaultPort = 8888;
    static const int defaultFd = -1;

public:
    PollServer(uint16_t port = defaultPort) : _port(port)
    {
    }
    ~PollServer()
    {
        _listenSock.Close();
    }

    void init()
    {
        logMessage(Debug, "PollServer init");

        _listenSock.Socket();
        _listenSock.Bind(_port);
        _listenSock.Listen();

        for (int i = 0; i < N; ++i) // init fd array
        {
            _fdArray[i].fd = defaultFd;
        }
        _fdArray[0].fd = _listenSock.Fd(); // 0 is listen fd
        _fdArray[0].events = POLLIN;       // listen fd is read event

        logMessage(Debug, "SelectServer init success");
    }

    void run()
    {
        logMessage(Debug, "PollServer run");

        // 1. 这里我们能够直接获取新的链接吗？
        // 2. 最开始的时候，我们的服务器是没有太多的sock的，甚至只有一个sock！listensock
        // 3. 在网络中， 新连接到来被当做 读事件就绪！
        // listensock_.Accept(); 不能！
        while (true)
        {
            // 1. 调用select
            int n = poll(_fdArray, N, -1);
            // 2. 判断结果
            if(n>0)
            {
                // 2.1 有事件就绪
                // 2.2 分类处理
                logMessage(Debug, "poll success");
                handlerEvent();
            }
            else if(n==0)
            {
                logMessage(Warning, "poll timeout");
                continue;
            }
            else
            {
                logMessage(Error, "poll error");
                continue;
            }
        }
    }

private:
    void handlerEvent()
    {
        logMessage(Debug, "handlerEvent ...");
        // 2.1 遍历fd_array，找到就绪的fd
        for (int i = 0; i < N; ++i)
        {
            int fd = _fdArray[i].fd;
            short event = _fdArray[i].revents;
            if (fd == defaultFd)
            {
                continue;
            }
            if ((event & POLLIN))
            {
                // 2.2 listensock就绪
                if (fd == _listenSock.Fd())
                {
                    accepter();
                }
                // 2.3 client sock就绪
                else
                {
                    serverIO(i);
                }
            }
        }
    }
    void accepter()
    {
        // 走到这里，说明listensock就绪了！调用accept是非阻塞的
        // 1. 调用accept
        std::string clientIP;
        uint16_t clientPort;
        int newsockfd = _listenSock.Accept(&clientIP, &clientPort);
        if(newsockfd < 0)
        {
            logMessage(Error, "accept error");
            return;
        }
        // 2. 将newsockfd添加到fd_array中
        bool flag = false;
        for (int i = 0; i < N; ++i)
        {
            if (_fdArray[i].fd == defaultFd)
            {
                _fdArray[i].fd = newsockfd;
                _fdArray[i].events = POLLIN;
                logMessage(Info, "new client:[%s:%d] connect success", clientIP.c_str(), clientPort);
                flag = true;
                break;
            }
        }
        if (!flag)
        {
            logMessage(Warning, "fd_array is full");
            close(newsockfd);
        }
    }

    void serverIO(int i)
    {
        // 走到这里，说明i client sock有数据到来了，调用recv是非阻塞的！
        // 1. 从fdArray中取出对应的信息
        int newsockfd = _fdArray[i].fd;
        // 2. recv
        std::string buf = _listenSock.Recv(newsockfd); // TODO
        if (buf == "")
        {
            // 2.1 对端关闭
            close(newsockfd);
            _fdArray[i].fd = defaultFd;
            logMessage(Info, "client shutdown: %d", newsockfd);
        }
        else
        {
            // 2.2 正常接收
            // 3. send
            _listenSock.Send(newsockfd, buf); // TODO 
        }
    }

private:
    uint16_t _port;
    SockTCP _listenSock;
    FDEvent_t _fdArray[N];
};
